<template>
  <el-dialog
    title="角色授权"
    :visible.sync="visible"
    width="37%"
    top="10vh"
    append-to-body
    :before-close="closeRoleMenuModifyDialogHandle"
    :close-on-click-modal="false"
    class="menu-role-dialog">

    <div class="filter">
      <span>菜单树交互</span>
      <el-checkbox v-model="menuTreeSearchVisible" @change="val => this.menuTreeSearchVisible = val" class="ml10">{{ menuTreeSearchVisible ? '关闭检索' : '菜单检索' }}</el-checkbox>
      <el-checkbox v-model="menuExpand" @change="menuTreeExpandHandle({ children: menuTree }, $event)">{{ menuExpand ? '折叠树' : '展开树' }}</el-checkbox>
      <el-checkbox v-model="menuNodeAll" @change="checkedTreeNodeAllHandle($event)">{{ menuNodeAll ? '取消全选' : '全选节点' }}</el-checkbox>
    </div>
    <div id="menuTree">
      <transition name="el-zoom-in-top">
        <el-row v-show="menuTreeSearchVisible" :gutter="10" class="search">
          <el-col :span="13" :offset="1">
            <el-input v-model="menuFilterText" clearable size="mini" placeholder="输入关键字进行过滤"
                      @clear="$refs.menuTree.filter(menuFilterText)"></el-input>
          </el-col>
          <el-col :span="4">
            <el-button :disabled="!menuFilterText || buttonLoad" type="primary" size="mini" icon="el-icon-search"
                       @click="$refs.menuTree.filter(menuFilterText)">查询</el-button>
          </el-col>
        </el-row>
      </transition>
      <el-tree
        v-loading="buttonLoad"
        element-loading-text="菜单树加载中"
        element-loading-spinner="el-icon-loading"
        empty-text="菜单树为空"
        show-checkbox
        highlight-current
        accordion
        node-key="menuId"
        :data="menuTree"
        :props="menuTreeProps"
        @node-expand="menuTreeExpandHandle($event, true)"
        :filter-node-method="filterTreeNode"
        ref="menuTree">
      </el-tree>
    </div>

    <span slot="footer" class="dialog-footer">
      <el-button @click="closeRoleMenuModifyDialogHandle">关 闭</el-button>
      <el-button :disabled="buttonLoad" type="primary" @click="relationHandle">确 定</el-button>
    </span>
  </el-dialog>
</template>

<script>

  export default {
    name: "menu-role-modify",
    data() {
      return {
        // 弹出框显示状态[true-显示 false-不显示]
        visible: false,
        // 角色主键
        roleId: undefined,
        // 菜单树数据
        menuTree: [],
        // 菜单树是否展开[true-是 false-不是]
        menuExpand: false,
        // 菜单树是否全选[true-是 false-不是]
        menuNodeAll: false,
        // 菜单树节点属性值配置
        menuTreeProps: {
          children: 'children',
          label: 'name'
        },
        // 菜单树检索输入框是否显示[true-显示 false-隐藏]
        menuTreeSearchVisible: false,
        // 菜单树检索内容
        menuFilterText: '',
        // 按钮是否可被点击[false-可以被点击 true-不可被点击]
        buttonLoad: false,
      }
    },
    computed: {
      // 主题颜色
      themeColor() {
        return this.$store.state.settings.theme
      },
    },
    methods: {
      /**
       * 初始化角色关联菜单弹出框方法
       * @param {string} roleId 角色主键
       */
      initRoleMenuModifyDialog(roleId) {
        // 打开弹出框
        this.visible = true
        this.roleId = roleId

        // 开始数据加载
        this.buttonLoad = true
        this.$axios.$get('/sys/role-menu/data', { params: { roleId }})
          .then(({ data }) => {
            this.menuTree = data.menuTree
            const menuIdList = data.menuIdList

            this.$nextTick(() => {
              let menuTree = this.$refs.menuTree
              menuIdList.forEach(menuId => {
                // 设置菜单树节点的选中状态
                menuTree.setChecked(menuId, true, false)
              })
            })
          })
          .catch(() => {})
          .finally(() => {
            // 数据加载结束
            this.buttonLoad = false
          })
      },
      /**
       * 菜单关联角色确认事件
       */
      relationHandle() {
        // 按钮不可被点击
        this.buttonLoad = true;

        // 目前被选中的部门树节点
        let checkedKeys = this.$refs.menuTree.getCheckedKeys()
        // 半选中的部门树节点
        let halfCheckedKeys = this.$refs.menuTree.getHalfCheckedKeys();
        // 合并
        halfCheckedKeys.push(...checkedKeys)
        // console.log('halfCheckedKeys', halfCheckedKeys);

        let formObj = {
          roleId: this.roleId,
          menuIds: halfCheckedKeys
        }
        this.$axios.$post('/sys/role-menu/update', formObj)
          .then(() => {
            this.notify('success', '操作成功', '角色关联菜单操作成功')

            this.closeRoleMenuModifyDialogHandle();
          })
          .catch(() => {})
          .finally(() => {
            // 按钮恢复可点击
            this.buttonLoad = false;
          })
      },
      /**
       * 菜单树节点选中状态变更事件（全选/全不选）
       * @param value 全选/全不选标记
       */
      checkedTreeNodeAllHandle(value) {
        this.$refs.menuTree.setCheckedNodes(value ? this.menuTree: []);
      },
      /**
       * 菜单树节点 展开/折叠 事件
       * @param {Object}  menu  菜单对象
       * @param {boolean} value 展开/折叠状态
       */
      menuTreeExpandHandle(menu, value) {
        let queue = [ menu.children ]
        let menuTree = this.$refs.menuTree;
        while (queue.length > 0) {
          let array = queue.shift();

          for (let childrenMenu of array) {
            // 展开 子节点 操作
            menuTree.store.nodesMap[childrenMenu.menuId].expanded = value;

            if (!!childrenMenu.children) {
              queue.push(childrenMenu.children)
            }
          }
        }
      },
      /**
       * 过滤菜单树节点事件
       * @param {string} searchWord 输入内容
       * @param {Object} menu       菜单数据对象
       */
      filterTreeNode(searchWord, menu) {
        if (!searchWord) {
          return true;
        }
        return menu.name.indexOf(searchWord) !== -1;
      },
      /**
       * 关闭角色授权弹出框事件
       */
      closeRoleMenuModifyDialogHandle() {
        // 清理角色主键
        this.roleId = undefined;
        // 清除菜单树数据
        this.menuTree = [];
        // 部门树检索输入框关闭
        this.menuTreeSearchVisible = false;
        // 清除部门树检索内容
        this.menuFilterText = '';
        this.$nextTick(() => {
          // 关闭弹出框
          this.visible = false;
        })
      }
    }
  }
</script>

<style scoped>
  .menu-role-dialog >>> .el-dialog__body {
    padding: 10px 20px;
  }
  .menu-role-dialog .filter {
    margin-bottom: 10px;
  }
  .menu-role-dialog #menuTree {
    border: 1px solid #e5e6e7;
    background: #fff none;
    border-radius: 4px;
    height: 400px;
    max-height: 400px;
    overflow-y: scroll;
  }
  #menuTree .search {
    width: 95%;
    padding: 10px;
  }
</style>
